#include "GlListener.h"

#include <algorithm>
#include "GlDistributor.h"

namespace GraphicLibrary
{
	//-----------------------------------------------
	template<typename ListenerType>
		Listener<ListenerType>::Listener()
			: mDistributor(0)
		{
		}

	//-----------------------------------------------
	template<typename ListenerType>
		void Listener<ListenerType>::connectedTo(const MyDistributor *distributor)
		{
			if(isConnected())
				disconnect();
			mDistributor = distributor;
			_Listener::connectedTo(distributor);
		}

	//-----------------------------------------------
	template<typename ListenerType>
		void Listener<ListenerType>::disconnectedFrom(const MyDistributor *distributor)
		{
			if(!isConnected())
				return;
			mDistributor = 0;
			_Listener::disconnectedFrom(distributor);
		}

	//-----------------------------------------------
	template<typename ListenerType>
		bool Listener<ListenerType>::isConnected() const
		{
#			pragma warning(disable: 4800)
			return mDistributor;
#			pragma warning(default: 4800)
		}

	//-----------------------------------------------
	template<typename ListenerType>
		const _Listener::MyDistributor* Listener<ListenerType>::getDistributor() const
		{
			return mDistributor;
		}

	//-----------------------------------------------
	template<typename ListenerType>
		Listener<ListenerType>::~Listener()
		{
			disconnect();
		}
	//-----------------------------------------------
	template<typename ListenerType>
		void Listener<ListenerType>::disconnect()
		{
			if(mDistributor)
				mDistributor->disconnect(this);
		}
}

namespace GraphicLibrary
{
	//-----------------------------------------------
	template<typename ListenerType>
		bool MultiListener<ListenerType>::Less::operator () (const MyDistributor *left, const MyDistributor *right) const
		{
			return left->getId() < right->getId();
		}
}

namespace GraphicLibrary
{
	//-----------------------------------------------
	template<typename ListenerType>
		MultiListener<ListenerType>::MultiListener()
			: mDistributors(new MyDistributorArray())
		{
		}

	//-----------------------------------------------
	template<typename ListenerType>
		void MultiListener<ListenerType>::connectedTo(const MyDistributor *distributor)
		{
			MyDistributorArray::iterator i = std::lower_bound(mDistributors->begin(), mDistributors->end(), distributor, Less());
			if(i == mDistributors->end() || (*i)->getId() != distributor->getId())
				mDistributors->insert(i, distributor);
			_Listener::connectedTo(distributor);
		}

	//-----------------------------------------------
	template<typename ListenerType>
		void MultiListener<ListenerType>::disconnectedFrom(const MyDistributor *distributor)
		{
			MyDistributorArray::iterator i = std::lower_bound(mDistributors->begin(), mDistributors->end(), distributor, Less());
			if(i != mDistributors->end() && (*i)->getId() == distributor->getId())
				mDistributors->erase(i);
			_Listener::disconnectedFrom(distributor);
		}

	//-----------------------------------------------
	template<typename ListenerType>
		bool MultiListener<ListenerType>::isConnectedTo(const MyDistributor *distributor) const
		{
			MyDistributorArray::iterator i = std::lower_bound(mDistributors->begin(), mDistributors->end(), distributor, Less());
			return i != mDistributors->end() && (*i)->getId() == distributor->getId();
		}

	//-----------------------------------------------
	template<typename ListenerType>
		MultiListener<ListenerType>::~MultiListener()
		{
			MyDistributorArray *distributors = mDistributors;
			mDistributors = new MyDistributorArray();

			for(MyDistributorArray::iterator i = distributors->begin(); i != distributors->end(); ++i)
				(*i)->disconnect(this);

			delete mDistributors;
			delete distributors;
		}
}
